package com.lifeverse.aspect;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.time.LocalDateTime;

/**
 * 数据库性能监控切面
 * 监控数据库操作的执行时间和性能指标
 */
@Aspect
@Component
@RequiredArgsConstructor
@Slf4j
public class DatabasePerformanceAspect {
    
    private final MeterRegistry meterRegistry;
    
    /**
     * 监控 Repository 方法执行
     */
    @Around("execution(* com.lifeverse.repository..*(..))")
    public Object monitorRepositoryMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        String operationName = className + "." + methodName;
        
        Timer.Sample sample = Timer.start(meterRegistry);
        LocalDateTime startTime = LocalDateTime.now();
        
        try {
            Object result = joinPoint.proceed();
            
            // 记录成功的数据库操作
            sample.stop(Timer.builder("database.query.duration")
                    .description("Database query execution time")
                    .tag("repository", className)
                    .tag("method", methodName)
                    .tag("status", "success")
                    .register(meterRegistry));
            
            Duration duration = Duration.between(startTime, LocalDateTime.now());
            long executionTimeMs = duration.toMillis();
            
            // 记录慢查询
            if (executionTimeMs > 1000) { // 超过1秒的查询
                log.warn("慢查询检测: {} 执行时间: {}ms", operationName, executionTimeMs);
                
                meterRegistry.counter("database.slow.query",
                        "repository", className,
                        "method", methodName)
                        .increment();
            }
            
            // 记录查询执行时间分布
            meterRegistry.timer("database.query.histogram",
                    "repository", className,
                    "method", methodName)
                    .record(duration);
            
            return result;
            
        } catch (Exception e) {
            // 记录失败的数据库操作
            sample.stop(Timer.builder("database.query.duration")
                    .description("Database query execution time")
                    .tag("repository", className)
                    .tag("method", methodName)
                    .tag("status", "error")
                    .register(meterRegistry));
            
            meterRegistry.counter("database.query.error",
                    "repository", className,
                    "method", methodName,
                    "exception", e.getClass().getSimpleName())
                    .increment();
            
            log.error("数据库操作异常: {} - {}", operationName, e.getMessage());
            throw e;
        }
    }
    
    /**
     * 监控 Service 层数据库相关方法
     */
    @Around("execution(* com.lifeverse.service..*(..)) && @annotation(org.springframework.transaction.annotation.Transactional)")
    public Object monitorTransactionalMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        String operationName = className + "." + methodName;
        
        Timer.Sample sample = Timer.start(meterRegistry);
        LocalDateTime startTime = LocalDateTime.now();
        
        try {
            Object result = joinPoint.proceed();
            
            sample.stop(Timer.builder("transaction.duration")
                    .description("Transaction execution time")
                    .tag("service", className)
                    .tag("method", methodName)
                    .tag("status", "success")
                    .register(meterRegistry));
            
            Duration duration = Duration.between(startTime, LocalDateTime.now());
            long executionTimeMs = duration.toMillis();
            
            // 记录长事务
            if (executionTimeMs > 5000) { // 超过5秒的事务
                log.warn("长事务检测: {} 执行时间: {}ms", operationName, executionTimeMs);
                
                meterRegistry.counter("transaction.long.running",
                        "service", className,
                        "method", methodName)
                        .increment();
            }
            
            return result;
            
        } catch (Exception e) {
            sample.stop(Timer.builder("transaction.duration")
                    .description("Transaction execution time")
                    .tag("service", className)
                    .tag("method", methodName)
                    .tag("status", "error")
                    .register(meterRegistry));
            
            meterRegistry.counter("transaction.error",
                    "service", className,
                    "method", methodName,
                    "exception", e.getClass().getSimpleName())
                    .increment();
            
            throw e;
        }
    }
}